package com.foreveross.crawl.adapter.sub.impl20140402.v3;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import net.htmlparser.jericho.Element;
import net.htmlparser.jericho.Source;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;

import com.foreveross.crawl.adapter.AbstractAdapter;
import com.foreveross.crawl.adapter.PlaneInfoEntityBuilder;
import com.foreveross.crawl.common.util.RegHtmlUtil;
import com.foreveross.crawl.domain.airfreight.AbstractPlaneInfoEntity;
import com.foreveross.crawl.domain.airfreight.CabinEntity;
import com.foreveross.crawl.domain.airfreight.TransitEntity;
import com.foreveross.crawl.domain.airfreight.doub.CabinRelationEntity;
import com.foreveross.crawl.domain.airfreight.doub.DoublePlaneInfoEntity;
import com.foreveross.crawl.domain.airfreight.doub.ReturnCabinEntity;
import com.foreveross.crawl.domain.airfreight.doub.ReturnDoublePlaneInfoEntity;
import com.foreveross.crawl.domain.airfreight.doub.ReturnTransitEntity;
import com.foreveross.crawl.domain.airfreight.single.SinglePlaneInfoEntity;
import com.foreveross.crawl.exception.FlightInfoNotFoundException;
import com.foreveross.taskservice.common.bean.TaskModel;

public class MalaysiaAdapter extends AbstractAdapter {

	public MalaysiaAdapter(TaskModel taskQueue) {
		super(taskQueue);
		// TODO Auto-generated constructor stub
	}

	private net.htmlparser.jericho.Source taxSource = null; 
	
	private String price;
	private String tax;
	private String totalPrice;
	
	@SuppressWarnings("unchecked")
	@Override
	public List<Object> paraseToVo(Object fetchObject) throws Exception {
		
//		List<AbstractPlaneInfoEntity> economys =  fetchFlight("Economy");
//		List<AbstractPlaneInfoEntity> businessFirsts =  fetchFlight("BusinessFirst");
		
		List<String[]> htmlArrs = (List<String[]>)fetchObject;
		
		List<AbstractPlaneInfoEntity> economys = this.buildEntity(htmlArrs.get(0));
		List<AbstractPlaneInfoEntity> businessFirsts = this.buildEntity(htmlArrs.get(1));
		
		List result = new ArrayList<AbstractPlaneInfoEntity>();
		Map<String,AbstractPlaneInfoEntity> economyMap = getFlightEntityMap(economys);
		Map<String,AbstractPlaneInfoEntity> businessFirstMap = getFlightEntityMap(businessFirsts);
		Set<String> aSet = businessFirstMap.keySet(),bSet = economyMap.keySet();
		List <AbstractPlaneInfoEntity> cList = new ArrayList<AbstractPlaneInfoEntity>();//没有交集的集合
		List <AbstractPlaneInfoEntity> dList = new ArrayList<AbstractPlaneInfoEntity>();//并集
		for(String a:aSet){
			if(!bSet.contains(a)){
				cList.add(businessFirstMap.get(a));
			}else{
				AbstractPlaneInfoEntity fClass = businessFirstMap.get(a);
				AbstractPlaneInfoEntity economy = economyMap.get(a);
				if(taskQueue.getIsReturn()==1){
					Set<CabinEntity> cabins = PlaneInfoEntityBuilder.getDoubleEntity(fClass).getCabins();
					Set<CabinRelationEntity> relations = PlaneInfoEntityBuilder.getDoubleEntity(fClass).getCabinRelations();
					PlaneInfoEntityBuilder.getDoubleEntity(economy).getCabins().addAll(cabins);
					PlaneInfoEntityBuilder.getDoubleEntity(economy).getCabinRelations().addAll(relations);
				}else{
					Set<CabinEntity> cabins = PlaneInfoEntityBuilder.getSingleEntity(fClass).getCabins();
					PlaneInfoEntityBuilder.getSingleEntity(economy).getCabins().addAll(cabins);
				}
				dList.add(economy);
			}
		}
		for(String b:bSet){
			if(!aSet.contains(b)){
				cList.add(economyMap.get(b));
			}
		}
		result.addAll(cList);
		result.addAll(dList);
		PlaneInfoEntityBuilder.buildLimitPrice(result);
		return result;
	}

	@Override
	public String getUrl() throws Exception {
		// TODO Auto-generated method stub
		return null;
	}
	
	@Override
	public Object fetch(String url) throws Exception {
		String economys =  fetchFlight("Economy");
		String businessFirsts =  fetchFlight("BusinessFirst");
		List <String[]> result = new ArrayList<String[]>();
		String [] html1 = {economys,"Economy"};
		String [] html2 = {businessFirsts,"BusinessFirst"};
		result.add(html1);
		result.add(html2);
		return result;
	}
	
	public Map<String,AbstractPlaneInfoEntity> getFlightEntityMap(List <AbstractPlaneInfoEntity> flightList){
		Map<String,AbstractPlaneInfoEntity> map = new HashMap<String,AbstractPlaneInfoEntity>();
		for(AbstractPlaneInfoEntity flight:flightList){
			if(taskQueue.getIsReturn()!=1){
				SinglePlaneInfoEntity entity = PlaneInfoEntityBuilder.getSingleEntity(flight);
				if(entity.getTransits().isEmpty()){
					map.put(flight.getFlightNo(), flight);
				}else{
					String key = "";
					for(TransitEntity transit:entity.getTransits()){
						key += transit.getFlightNo()+"_";
					}
					key = key.substring(0, key.length()-1);
					map.put(key, flight);
				}
			}else{
				DoublePlaneInfoEntity entity = PlaneInfoEntityBuilder.getDoubleEntity(flight);
				if(entity.getTransits().isEmpty()){
					map.put(flight.getFlightNo(), flight);
				}else{
					String key = "";
					for(TransitEntity transit:entity.getTransits()){
						key += transit.getFlightNo()+"_";
					}
					key = key.substring(0, key.length()-1);
					map.put(key, flight);
				}
			}
		}
		return map;
	}

	private String fetchFlight(String cabinType) throws Exception{
		
		DefaultHttpClient httpClient = (DefaultHttpClient)this.getHttpClient();
		Object[] servlet = null;
		String tripType = taskQueue.getIsReturn()==1?"tripType=RT": "tripType=OW";
		String[] toDateArr = taskQueue.getFlightDate().split("-");
		String [] returnDateArr = taskQueue.getIsReturn()==1?taskQueue.getReturnGrabDate().split("-"):null;
		String inboundOption = "";
		if(returnDateArr!=null){
			inboundOption = "&inboundOption.departureDay="+returnDateArr[2]+"&inboundOption.departureMonth="+returnDateArr[1]+"&inboundOption.departureYear="+returnDateArr[0];
		}
		
		String url = "https://bookings.malaysiaairlines.com/MHOnline/AirLowFareSearchExternal.do?"+tripType+"&outboundOption.originLocationCode="+super.taskQueue.getFromCity()+"&outboundOption.destinationLocationCode="+super.taskQueue.getToCity()+"&outboundOption.departureDay="+toDateArr[2]+"&outboundOption.departureMonth="+toDateArr[1]+"&outboundOption.departureYear="+toDateArr[0]+inboundOption+"&guestTypes[0].type=ADT&guestTypes[0].amount=1&guestTypes[1].type=CNN&guestTypes[1].amount=0&guestTypes[2].type=INF&guestTypes[2].amount=0&cabinClass="+cabinType+"&lang=zh_CN&pos=MAS&flexibleSearch=true";
//		System.out.println(url);
		HttpPost request = new HttpPost(url);
		HttpResponse reponse = httpClient.execute(request);
//		System.out.println(httpClient.getCookieStore().toString());
		HttpEntity entity = reponse.getEntity();
		String page = EntityUtils.toString(entity,"GBK");
//		System.out.println(page);
		String jsess = RegHtmlUtil.regStr(page, "'AirLowFareSearchExt.do(;jsessionid=.+?)'");
		request = new HttpPost("https://bookings.malaysiaairlines.com/MHOnline/AirLowFareSearchExt.do"+jsess+"?ajaxAction=true");
		reponse = httpClient.execute(request);
		EntityUtils.consume(reponse.getEntity());
//		System.out.println(httpClient.getCookieStore().toString());
		request = new HttpPost("https://bookings.malaysiaairlines.com/MHOnline/AirFareFamiliesFlexibleForward.do"+jsess);
		reponse = httpClient.execute(request);
		entity = reponse.getEntity();
		String html = EntityUtils.toString(entity,"GBK");
//		System.out.println(html);
		//获取税收 html
		//随机一个价格进入，得到对应的税收HTML
		
		
		request.setHeader("Cookie", "currentLang=zh_CN;");
		request = new HttpPost("https://bookings.malaysiaairlines.com/MHOnline/AirSelectOWCFlight.do?alignment=vertical&combinabilityReloadRequired=false&context=airSelection&flightIndex=&flowStep=AIR_COMBINABLE_FARE_FAMILIES_SEARCH_RESULTS&isFareFamilySearchResult=true&selectedFlightIds=0%2C0&selectedItineraries=0%2C0");
		reponse = httpClient.execute(request);
		entity = reponse.getEntity();
		EntityUtils.consume(entity);
//		String html3 = EntityUtils.toString(entity,"GBK");
//		System.out.println(html3);
		
		request = new HttpPost("https://bookings.malaysiaairlines.com/MHOnline/AirVerifyFareFamiliesItinerary.do");
		reponse = httpClient.execute(request);
		entity = reponse.getEntity();
//		String html5 = EntityUtils.toString(entity,"GBK");
//		System.out.println(html5);
		
		
		String url2="https://bookings.malaysiaairlines.com/MHOnline/AirFareFamiliesForward.do";
		try{
		String cookies=reponse.getFirstHeader("Cookie").getValue();
		HttpPost request2 = new HttpPost();
		request2.setHeader("Cookie",cookies);
		request2.setHeader("x-requested-with", "XMLHttpRequest");
		request2.setHeader("Accept-Language", "zh-cn,en-us;q=0.8,zh;q=0.5,en;q=0.3");
		request2.setHeader("Referer",url2);
		request2.setHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
		request2.setHeader("Accept-Encoding", "gzip, deflate");
		request2.setHeader("Host", "bookings.malaysiaairlines.com");
		HttpResponse reponse2 = httpClient.execute(request2);
		HttpEntity entity2=reponse2.getEntity();
		
		taxSource=new Source(entity2.getContent());
		}catch(Exception e){
//			throw new Exception("获取税收信息错误！");
			e.getMessage();
			taxSource=null;
		}
		
		return html;
	}
	
	//处理税收信息价格
	public void taxInfo(Source sources){
		List<Element> taxClass=sources.getAllElementsByClass("colPrice colTaxes");
		for(Element taxDiv:taxClass){
			List<Element>divList=taxDiv.getAllElements("div");
			if(divList.size()>0){
				price=divList.get(0).getTextExtractor().toString();
				tax=divList.get(1).getTextExtractor().toString();
				totalPrice=divList.get(2).getTextExtractor().toString();
				break;
			}
			
		}
	}
	
	public List buildEntity(String[] htmls) throws Exception{
		String html = htmls[0];
//		System.out.println(html);
		if(StringUtils.contains(html, "errors.air.lowFareSearch.NO_FLIGHTS_FOUND")){
			throw new FlightInfoNotFoundException();
		}
		String cabinType = htmls[1];
//		System.out.println(httpClient.getCookieStore().toString());errors.air.lowFareSearch.NO_FLIGHTS_FOUND
		List<AbstractPlaneInfoEntity> result = getFlightInfos(false,cabinType,html);
		if(taskQueue.getIsReturn()!=1){
			return result;
		}
		List returnResult = getFlightInfos(true,cabinType,html);
		for(AbstractPlaneInfoEntity from :result){
			 PlaneInfoEntityBuilder.getDoubleEntity(from).getReturnPlaneInfos().addAll(returnResult);
		 }
		PlaneInfoEntityBuilder.buildRelation(result, returnResult);
		return result;
	} 
	
	private List getFlightInfos(Boolean isReturn,String cabinType,String html) throws Exception{
		double prices=0.0,taxs=0.0,totalPrices=0.0;
		if(taxSource !=null){
			this.taxInfo(taxSource);
			if(this.price !=null && !this.price.equals("")) prices=Double.parseDouble(price);
			if(this.tax !=null && !this.tax.equals("")) taxs=Double.parseDouble(tax);
			if(this.totalPrice !=null && !this.totalPrice.equals("")) totalPrices=Double.parseDouble(totalPrice);
		}
		
		List<AbstractPlaneInfoEntity> result = new ArrayList<AbstractPlaneInfoEntity>();
		if(StringUtils.isBlank(html)){
			return result;
		}
		String from = RegHtmlUtil.regStr(html, this.getRegex1(isReturn));
		//System.out.println(RegHtmlUtil.regStr(from, this.getRegex2()));
		if(StringUtils.isBlank(from)){
			return result;
		}
		
		
		from = from.replace("\\u003e", ">").replace("\\u003c", "<").replace("\\\"", "\"").replace("\\t", "\t").replace("\\n", "\n");
		List<String> flightStrs = RegHtmlUtil.retrieveLinks(from, this.getRegex2(),0);
		
		for(String flightStr:flightStrs){
				//航班号 开始时间 结束时间 起飞地中文 起飞三字码 到达地中文 到达三字码 价格信息
			List <List<String>> oneflights = RegHtmlUtil.retrieveLinkss(flightStr, this.getRegex3());
			List <String> firstTransit = oneflights.get(0);
			List<String> lastTransit = oneflights.get(oneflights.size()-1);
			String flightNo = firstTransit.get(1);
			String beginTime = firstTransit.get(2).replaceAll("<.+?>", "");
			String endTime = lastTransit.get(3).replaceAll("<.+?>", "");
			AbstractPlaneInfoEntity flightInfo = null;
			if(isReturn){
				flightInfo = PlaneInfoEntityBuilder.buildPlaneInfo(taskQueue, "MH", "马航", "马来西亚",beginTime, endTime, flightNo, null, null, null, null,ReturnDoublePlaneInfoEntity.class);
			}else{
				flightInfo = PlaneInfoEntityBuilder.buildPlaneInfo(taskQueue, "MH", "马航", "马来西亚",beginTime, endTime, flightNo, null, null, null, null);
			}
			
			
			//马航的价格信息都是发展航班显示第一行的
			String priceHtml = firstTransit.get(8);
			List<String> priceStrs = RegHtmlUtil.retrieveLinks(priceHtml, this.getRegex5(), 1);
			//排序价格
			if(priceStrs.size()>0){
				Collections.sort(priceStrs);
			}
			
			if(priceStrs.size()>0){
				flightInfo.setTotalLowestPrice(Double.parseDouble(priceStrs.get(0).replaceAll("\\,", "")));
				flightInfo.setTotalHighestPrice(Double.parseDouble(priceStrs.get(priceStrs.size()-1).replaceAll("\\,", "")));
			}else{
				flightInfo.setTotalLowestPrice(0.0);
				flightInfo.setTotalHighestPrice(0.0);
			}
			
			for(String priceStr:priceStrs){
				this.buildCabin(isReturn, flightInfo, getCabinTypeCN(cabinType), null, null,PlaneInfoEntityBuilder.getDouble(priceStr));
			}
			flightInfo.setSumHighestPrice(flightInfo.getTotalHighestPrice()+totalPrices);
			flightInfo.setSumLowestPrice(flightInfo.getTotalLowestPrice()+totalPrices);
			flightInfo.setTotalLowestTaxesPrice(totalPrices);
			flightInfo.setTotalHighestTaxesPrice(totalPrices);
			result.add(flightInfo);
			if(oneflights.size()<=1){
				continue;
			}
			
			for(List<String> one:oneflights){
				setTransitEntity(isReturn, firstTransit, flightInfo, one);
			}
			
		}
		return result;
	}

	private void setTransitEntity(Boolean isReturn, List<String> firstTransit,
			AbstractPlaneInfoEntity flightInfo, List<String> one) throws Exception {
		
		TransitEntity transit = new TransitEntity();
		transit.setActuallyFlightNo(firstTransit.get(1));
		Date begin = null,end;
		if(isReturn){
			begin = PlaneInfoEntityBuilder.getFlightTime(taskQueue.getReturnGrabDate(), one.get(2).replaceAll("<.+?>", ""));
			end = PlaneInfoEntityBuilder.getFlightTime(taskQueue.getReturnGrabDate(), one.get(3).replaceAll("<.+?>", ""));
		}else{
			begin = PlaneInfoEntityBuilder.getFlightTime(taskQueue.getFlightDate(), one.get(2).replaceAll("<.+?>", ""));
			end = PlaneInfoEntityBuilder.getFlightTime(taskQueue.getFlightDate(), one.get(3).replaceAll("<.+?>", ""));
		}////航班号 开始时间 结束时间 起飞地中文 起飞三字码 到达地中文 到达三字码 价格信息
		
		if(isReturn){
			ReturnTransitEntity transitEntity = PlaneInfoEntityBuilder.buildTransitEntity(one.get(1), firstTransit.get(1), null, null, null,
					one.get(5), one.get(4), one.get(7), one.get(6), null,ReturnTransitEntity.class);
			transitEntity.setStartTime(begin);
			transitEntity.setEndTime(end);
			PlaneInfoEntityBuilder.getReturnDoubleEntity(flightInfo).getReturnTransits().add(transitEntity);
		}else{
			TransitEntity transitEntity = PlaneInfoEntityBuilder.buildTransitEntity(one.get(1), firstTransit.get(1), null, null, null,
					one.get(5), one.get(4), one.get(7), one.get(6), null,TransitEntity.class);
			transitEntity.setStartTime(begin);
			transitEntity.setEndTime(end);
			if(taskQueue.getIsReturn()==1){
				PlaneInfoEntityBuilder.getDoubleEntity(flightInfo).getTransits().add(transitEntity);
			}else{
				PlaneInfoEntityBuilder.getSingleEntity(flightInfo).getTransits().add(transitEntity);
			}
		}
	}
	
	public String getCabinTypeCN(String cabinType){
		if("Economy".equals(cabinType)){
			return "经济舱";
		}else{
			return "商务/头等舱";
		}
	}
	
	

	
//	private void loadRequestHeader(HttpUriRequest request) {
//		request.setHeader("Accept","text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
//				request.setHeader("Accept-Charset", "GBK,utf-8;q=0.7,*;q=0.3");
//				request.setHeader("Host","bookings.malaysiaairlines.com");
//				request.setHeader("Content-Type","application/x-www-form-urlencoded");
//				request.setHeader("Referer","https://bookings.malaysiaairlines.com/MHOnline/AirLowFareSearchExternal.do?tripType=RT&outboundOption.originLocationCode=BKK&outboundOption.destinationLocationCode=CAN&outboundOption.departureDay=16&outboundOption.departureMonth=05&outboundOption.departureYear=2014&inboundOption.departureDay=26&inboundOption.departureMonth=06&inboundOption.departureYear=2014&guestTypes%5B0%5D.type=ADT&guestTypes%5B0%5D.amount=1&guestTypes%5B1%5D.type=CNN&guestTypes%5B1%5D.amount=0&guestTypes%5B2%5D.type=INF&guestTypes%5B2%5D.amount=0&cabinClass=Economy&lang=zh_CN&pos=MAS&flexibleSearch=true");
//				request.setHeader("Vary", "Accept-Encoding,User-Agent");
//	}
//	@Override
	public boolean validateFetch(Object fetchObject) throws Exception {
		// TODO Auto-generated method stub
		return true;
	}
	
	private String getRegex1(Boolean isReturn){
		int r = 0;
		if(isReturn){
			r=1;
		}
		String regex = "tdGroupData\\["+r+"\\].*?\\{(.+?)\\};";
		return regex;
	}
	
	private String getRegex2(){
		String regex = "<tbody.*?>.+?</tbody>";
		return regex;
	}
	
//	private String getRegex3(){
//		String regex = "showFlightDetailsPopUp.+?>.+?(?:</tr>\\s*?<tr class|</tr>\\s*?</tbody>)";
//		//价格信息
////		regex +="(.+)";//
//		return regex;
//	}
	/**
	 * 航班号 开始时间 结束时间 起飞地中文 起飞三字码 到达地中文 到达三字码 价格信息
	 * @return
	 */
	private static String getRegex3(){
		//航班号 开始时间 结束时间
		String regex = "showFlightDetailsPopUp.+?>(.+?)<.+?<td.+?<div\\s*?>(.+?)</div>.*?<td.+?<div\\s*?>(.+?)</div>";
		//起飞地中文 起飞三字码 到达地中文 到达三字码
		regex += ".*?<td.+?<div\\s*?>\\s*?<span\\s*?title=\"(.+?),.+?\"\\s*?>(.+?)</span>.+?<span\\s*?title=\"(.+?),.+?\"\\s*?>(.+?)</span>";
		regex += "(.+?(?=</tr>\\s*?<tr class|</tr>\\s*?</tbody>))";
		return regex ;
	}
	
	private String getRegex5(){
		String regex = "<table>.+?<label\\s*?for.+?>(.+?)</label>";
		return regex;
	}
	
	
	private void buildCabin(boolean isReturn,AbstractPlaneInfoEntity planeInfo,String cabinType,String subCabinName,String productName,Double price){
		if(isReturn){
			ReturnCabinEntity cabinEntity = new ReturnCabinEntity();
			cabinEntity.setCabinType(cabinType);
			cabinEntity.setPlaneInfoEntity(planeInfo);
			cabinEntity.setPrice(price);
			cabinEntity.setProductName(productName);
			cabinEntity.setSubCabinName(subCabinName);
			PlaneInfoEntityBuilder.getReturnDoubleEntity(planeInfo).getReturnCabins().add(cabinEntity);
		}else{
			CabinEntity cabinEntity = new CabinEntity();
			cabinEntity.setCabinType(cabinType);
			cabinEntity.setPlaneInfoEntity(planeInfo);
			cabinEntity.setPrice(price);
			cabinEntity.setProductName(productName);
			cabinEntity.setSubCabinName(subCabinName);
			if(this.taskQueue.getIsReturn()==1){
				PlaneInfoEntityBuilder.getDoubleEntity(planeInfo).getCabins().add(cabinEntity);
			}else{
				PlaneInfoEntityBuilder.getSingleEntity(planeInfo).getCabins().add(cabinEntity);
			}
		}
	}
	
	
	public static void main(String[] args) throws Exception {
//	ApplicationContext context = new ClassPathXmlApplicationContext("application-rest-client.xml");
//	IProxyIPService aa = (IProxyIPService) context
//	.getBean("useProxyIPService");
//	ProxyIpDTO bb = aa.getProxyIp("3b9a4ff0914769cb", "1");
	
	List<String> testlist=new ArrayList<String>(1);
//	testlist.add("2,111");
//	testlist.add("2,121");
//	testlist.add("2,113");
//	testlist.add("11");
//	testlist.add("23,111");
//	testlist.add("93,111");
//	testlist.add("13,111");
//	Collections.sort(testlist);
		
	TaskModel taskQueue = new TaskModel();
	taskQueue.setIsInternational(1);
	taskQueue.setFlightDate("2014-07-11");
	taskQueue.setReturnGrabDate("2014-07-30");
	taskQueue.setIsReturn(1);
//	taskQueue.setFromCity("CTU");
	taskQueue.setFromCity("CAN");
	taskQueue.setToCity("KUL");
	
//	aa = aa.replace("\\\"", "\"").replace("\\t", "\t").replace("\\n", "\n");
//	List<List<String>> list = RegHtmlUtil.retrieveLinkss(aa,getRegex4());
//	for(List<String>cells:list){
//		System.out.println(cells.size());
//		for(String cell:cells){
//			System.out.printl n(cell);
//		}
//	}
	
	MalaysiaAdapter a = new MalaysiaAdapter(taskQueue);
//	a.proxyIp = new ProxyIpModel(bb.getIp(), bb.getPort());
	a.paraseToVo(a.fetch(null));
}
	

}

